<?php
namespace Mkd\Core;

use Mkd\Route\Route;
use Mkd\Request\Request;
use	Symfony\Component\HttpFoundation\Response;

class Mkd
{
	public function __construct()
	{
		set_exception_handler('Mkd\Core\Mkd::onException');
		define('ROOT', realpath(__DIR__.'/../../'));
	}

	public function run()
	{
		$route = Route::matchRoute();

		$controller = $route['controller'];

		/**
		 * 通过反射机制获取控制器内的方法
		 */
		$reflection = new \ReflectionClass($controller);
		$methods = $reflection->getMethods();
		$method = null;

		/**
		 * 匹配路由与action
		 */
		foreach ($methods as $m) {
			if ($m->getName() === $route['action']) {
				$method = $m;
				break;
			}
		}

		if ($method === null) {
			throw new \Exception("To be called method {$route['action']} dose not exists in {$controller}");
		}

		/**
		 * 通过反射机制获取action所需的参数
		 */
		$reflectionMethod = new \ReflectionMethod($route['controller'], $method->getName());
		$methodPatameters = $reflectionMethod->getParameters();

		/**
		 * 组装action所需的参数
		 */
		$args = [];
		foreach ($methodPatameters as $refm) {
			array_push($args, $refm->name);
		}

		/**
		 * 生成注入action的参数
		 */
		$parameters = [];
		foreach ($args as $arg) {
			$reflectionParameter = new \ReflectionParameter([$controller, $method->getName()], $arg);
			$parameters[$reflectionParameter->getPosition()] = isset($route[$arg]) ? $route[$arg] : null;
		}


		$instance = new $controller;

		/**
		 * 把处理请求交给控制器
		 */
		$response = call_user_func_array(array(
			$instance,
			$method->getName()
		), 
		$parameters);


		/**
		 * 相应客户端的请求
		 */
		if ($response instanceof Response) {
			$response->send();
		} else 	if (is_array($response) && (list($twig, $template, $parameters) = $response) && ($twig instanceof \Twig_Environment)) {
				echo $template->render($parameters);
		} else {
			throw new \Exception("An action must be return a response of a render with template");
		}

	}

	/**
	 * 简单的Exception处理函数
	 */
	public static function onException($exception)
	{
		echo "A Fatal Error thrown in {$exception->getFile()} at line {$exception->getLine()}<br />";
		echo "Message: ".$exception->getMessage();
	}
}

?>
